import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
import threading

class DocxConverterApp:
    def __init__(self, root):
        self.root = root
        self.root.title("DOCX 文件转换工具")
        self.root.geometry("800x600")
        self.root.resizable(True, True)
        
        # 设置主题
        self.style = ttk.Style()
        self.style.theme_use('clam')
        
        # ========== 新增：创建可滚动主区域 ==========
        # 创建一个主Frame，填充整个窗口
        main_frame = tk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 创建Canvas和垂直滚动条
        self.canvas = tk.Canvas(main_frame)
        v_scrollbar = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=self.canvas.yview)
        self.canvas.configure(yscrollcommand=v_scrollbar.set)

        # 滚动条和Canvas布局
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        v_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

        # 在Canvas里创建一个Frame，所有内容都放到这个Frame里
        self.content_frame = tk.Frame(self.canvas)
        self.canvas.create_window((0, 0), window=self.content_frame, anchor="nw")

        # 绑定Frame大小变化时，自动调整Canvas滚动区域
        self.content_frame.bind("<Configure>", lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all")))

        # ========== 下面所有控件都放 self.content_frame ==========
        self.create_widgets()
        self.setup_layout()
        
        # 初始化变量
        self.input_files = []
        self.output_folder = ""
        
    def create_widgets(self):
        # 文件选择区域
        self.file_frame = ttk.LabelFrame(self.content_frame, text="选择 DOCX 文件")
        self.file_frame.pack(fill="x", padx=10, pady=5)
        
        self.add_button = ttk.Button(self.file_frame, text="添加文件", command=self.add_files)
        self.add_button.pack(side="left", padx=5, pady=5)
        
        self.add_folder_button = ttk.Button(self.file_frame, text="添加文件夹", command=self.add_folder)
        self.add_folder_button.pack(side="left", padx=5, pady=5)
        
        self.clear_button = ttk.Button(self.file_frame, text="清空列表", command=self.clear_files)
        self.clear_button.pack(side="left", padx=5, pady=5)
        
        # 文件列表
        self.file_list = tk.Listbox(self.file_frame, height=8, selectmode=tk.EXTENDED)
        self.file_list.pack(fill="both", expand=True, padx=5, pady=5)
        
        # 输出目录选择
        self.output_frame = ttk.LabelFrame(self.content_frame, text="输出设置")
        self.output_frame.pack(fill="x", padx=10, pady=5)
        
        self.output_label = ttk.Label(self.output_frame, text="输出目录:")
        self.output_label.pack(side="left", padx=5, pady=5)
        
        self.output_entry = ttk.Entry(self.output_frame, width=50)
        self.output_entry.pack(side="left", fill="x", expand=True, padx=5, pady=5)
        
        self.browse_button = ttk.Button(self.output_frame, text="浏览...", command=self.select_output_folder)
        self.browse_button.pack(side="left", padx=5, pady=5)
        
        # 转换选项
        self.options_frame = ttk.LabelFrame(self.content_frame, text="转换选项")
        self.options_frame.pack(fill="x", padx=10, pady=5)
        
        # 文本转换
        self.text_frame = ttk.Frame(self.options_frame)
        self.text_frame.pack(fill="x", padx=5, pady=5)
        
        self.case_var = tk.StringVar(value="none")
        self.case_label = ttk.Label(self.text_frame, text="文本大小写:")
        self.case_label.pack(side="left", padx=5, pady=2)
        self.lower_radio = ttk.Radiobutton(self.text_frame, text="小写", variable=self.case_var, value="lower")
        self.lower_radio.pack(side="left", padx=5, pady=2)
        self.upper_radio = ttk.Radiobutton(self.text_frame, text="大写", variable=self.case_var, value="upper")
        self.upper_radio.pack(side="left", padx=5, pady=2)
        self.title_radio = ttk.Radiobutton(self.text_frame, text="标题格式", variable=self.case_var, value="title")
        self.title_radio.pack(side="left", padx=5, pady=2)
        self.none_radio = ttk.Radiobutton(self.text_frame, text="无", variable=self.case_var, value="none")
        self.none_radio.pack(side="left", padx=5, pady=2)
        
        # 查找替换
        self.find_frame = ttk.Frame(self.options_frame)
        self.find_frame.pack(fill="x", padx=5, pady=5)
        
        self.find_label = ttk.Label(self.find_frame, text="查找:")
        self.find_label.pack(side="left", padx=5, pady=2)
        self.find_entry = ttk.Entry(self.find_frame, width=20)
        self.find_entry.pack(side="left", padx=5, pady=2)
        
        self.replace_label = ttk.Label(self.find_frame, text="替换为:")
        self.replace_label.pack(side="left", padx=5, pady=2)
        self.replace_entry = ttk.Entry(self.find_frame, width=20)
        self.replace_entry.pack(side="left", padx=5, pady=2)
        
        # 水印设置
        self.watermark_frame = ttk.Frame(self.options_frame)
        self.watermark_frame.pack(fill="x", padx=5, pady=5)
        
        self.watermark_var = tk.BooleanVar(value=False)
        self.watermark_check = ttk.Checkbutton(
            self.watermark_frame, 
            text="添加水印:", 
            variable=self.watermark_var,
            command=self.toggle_watermark
        )
        self.watermark_check.pack(side="left", padx=5, pady=2)
        
        self.watermark_entry = ttk.Entry(self.watermark_frame, width=20, state="disabled")
        self.watermark_entry.pack(side="left", padx=5, pady=2)
        
        # 文件名前缀
        self.prefix_frame = ttk.Frame(self.options_frame)
        self.prefix_frame.pack(fill="x", padx=5, pady=5)
        
        self.prefix_label = ttk.Label(self.prefix_frame, text="文件名前缀:")
        self.prefix_label.pack(side="left", padx=5, pady=2)
        self.prefix_entry = ttk.Entry(self.prefix_frame, width=20)
        self.prefix_entry.pack(side="left", padx=5, pady=2)
        
        # 进度条和日志
        self.progress_frame = ttk.Frame(self.content_frame)
        self.progress_frame.pack(fill="x", padx=10, pady=5)
        
        self.progress = ttk.Progressbar(self.progress_frame, orient="horizontal", length=100, mode="determinate")
        self.progress.pack(fill="x", padx=5, pady=5)
        
        self.log_frame = ttk.LabelFrame(self.content_frame, text="日志")
        self.log_frame.pack(fill="both", expand=True, padx=10, pady=5)
        
        self.log_text = tk.Text(self.log_frame, height=8)
        self.log_text.pack(fill="both", expand=True, padx=5, pady=5)
        self.log_text.config(state="disabled")
        
        # 控制按钮
        self.button_frame = ttk.Frame(self.content_frame)
        self.button_frame.pack(fill="x", padx=10, pady=10)
        
        self.convert_button = ttk.Button(self.button_frame, text="开始转换", command=self.start_conversion)
        self.convert_button.pack(side="left", padx=5, pady=5)
        
        self.exit_button = ttk.Button(self.button_frame, text="退出", command=self.root.quit)
        self.exit_button.pack(side="right", padx=5, pady=5)
    
    def setup_layout(self):
        # 添加一些样式
        self.style.configure("TButton", padding=6)
        self.style.configure("TFrame", background="#f0f0f0")
        
    def add_files(self):
        files = filedialog.askopenfilenames(
            title="选择 DOCX 文件",
            filetypes=[("Word 文档", "*.docx"), ("所有文件", "*.*")]
        )
        if files:
            for file in files:
                if file not in self.input_files:
                    self.input_files.append(file)
                    self.file_list.insert(tk.END, file)
    
    def add_folder(self):
        folder = filedialog.askdirectory(title="选择文件夹")
        if folder:
            for root, dirs, files in os.walk(folder):
                for file in files:
                    if file.lower().endswith(".docx"):
                        file_path = os.path.join(root, file)
                        if file_path not in self.input_files:
                            self.input_files.append(file_path)
                            self.file_list.insert(tk.END, file_path)
    
    def clear_files(self):
        self.input_files = []
        self.file_list.delete(0, tk.END)
    
    def select_output_folder(self):
        folder = filedialog.askdirectory(title="选择输出文件夹")
        if folder:
            self.output_folder = folder
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, folder)
    
    def toggle_watermark(self):
        if self.watermark_var.get():
            self.watermark_entry.config(state="normal")
        else:
            self.watermark_entry.config(state="disabled")
    
    def log_message(self, message):
        self.log_text.config(state="normal")
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.log_text.config(state="disabled")
        self.root.update_idletasks()
    
    def start_conversion(self):
        if not self.input_files:
            messagebox.showwarning("警告", "请至少选择一个DOCX文件！")
            return
            
        if not self.output_folder:
            messagebox.showwarning("警告", "请选择输出目录！")
            return
            
        # 获取转换选项
        options = {
            "case": self.case_var.get(),
            "find_text": self.find_entry.get(),
            "replace_text": self.replace_entry.get(),
            "watermark": self.watermark_entry.get() if self.watermark_var.get() else None,
            "prefix": self.prefix_entry.get()
        }
        
        # 禁用按钮，防止重复点击
        self.convert_button.config(state="disabled")
        self.add_button.config(state="disabled")
        self.add_folder_button.config(state="disabled")
        self.clear_button.config(state="disabled")
        
        # 启动转换线程
        self.progress["value"] = 0
        self.log_text.config(state="normal")
        self.log_text.delete(1.0, tk.END)
        self.log_text.config(state="disabled")
        
        thread = threading.Thread(
            target=self.convert_files, 
            args=(self.input_files, self.output_folder, options),
            daemon=True
        )
        thread.start()
    
    def convert_files(self, files, output_folder, options):
        total_files = len(files)
        for i, file_path in enumerate(files):
            try:
                # 更新进度
                progress = (i + 1) / total_files * 100
                self.progress["value"] = progress
                
                # 处理文件名
                file_name = os.path.basename(file_path)
                output_name = f"{options['prefix']}{file_name}"
                output_path = os.path.join(output_folder, output_name)
                
                self.log_message(f"正在处理: {file_name}")
                
                # 执行转换
                self.convert_docx(file_path, output_path, options)
                
                self.log_message(f"成功转换: {output_name}")
                
            except Exception as e:
                self.log_message(f"错误: 处理 {file_name} 时出错 - {str(e)}")
        
        # 完成后启用按钮
        self.convert_button.config(state="normal")
        self.add_button.config(state="normal")
        self.add_folder_button.config(state="normal")
        self.clear_button.config(state="normal")
        
        self.log_message("转换完成！")
        messagebox.showinfo("完成", f"已成功转换 {len(files)} 个文件")
    
    def convert_docx(self, input_path, output_path, options):
        # 打开原始文档
        doc = Document(input_path)
        
        # 文本大小写转换
        if options["case"] != "none":
            for paragraph in doc.paragraphs:
                for run in paragraph.runs:
                    text = run.text
                    if options["case"] == "lower":
                        run.text = text.lower()
                    elif options["case"] == "upper":
                        run.text = text.upper()
                    elif options["case"] == "title":
                        run.text = text.title()
        
        # 查找替换
        if options["find_text"]:
            for paragraph in doc.paragraphs:
                if options["find_text"] in paragraph.text:
                    paragraph.text = paragraph.text.replace(
                        options["find_text"], 
                        options["replace_text"]
                    )
        
        # 添加水印
        if options["watermark"]:
            watermark = options["watermark"]
            for section in doc.sections:
                header = section.header
                paragraph = header.paragraphs[0] if header.paragraphs else header.add_paragraph()
                paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
                
                # 清除已有的水印
                for run in paragraph.runs:
                    run.clear()
                
                run = paragraph.add_run(watermark)
                run.font.size = Pt(40)
                run.font.color.rgb = RGBColor(200, 200, 200)  # 浅灰色
                run.font.name = "Arial"
                r = run._element
                r.rPr.rFonts.set(qn('w:eastAsia'), '微软雅黑')  # 设置中文字体
        
        # 保存新文档
        doc.save(output_path)

if __name__ == "__main__":
    root = tk.Tk()
    app = DocxConverterApp(root)
    root.mainloop()